﻿using System.Diagnostics;
using DimensionsHelper.Common.Utils;
using DimensionsHelper.LanguageService.Protocol;
using DimensionsHelper.LanguageService.Symbols;
using DimensionsHelper.LanguageService.Syntax;

namespace DimensionsHelper.LanguageService;

/// <summary>
///     此类<see cref="Binder" />只绑定<see cref="SourceFileType.Mrs" />类型的源文件代码。
/// </summary>
public class MrsBinder(WorkFolder workFolder) : Binder(workFolder)
{
    private const byte Any = 0;
    private const byte Int = 1;
    private const byte Dbl = 2;
    private const byte Bln = 3;
    private const byte Str = 4;
    private const byte Dat = 5;
    private const byte Cat = 6;

    private const byte OpNon = 0;
    private const byte OpRtC = 1;
    private const byte OpCtR = 2;
    private const byte OpRow = 3;
    private const byte OpCol = 4;
    private const byte OpInt = 5;

    private const byte OpAdd = 0;
    private const byte OpSubtract = 1;
    private const byte OpMultiply = 2;
    private const byte OpDivide = 3;
    private const byte OpModulo = 4;

    private static readonly byte[][] BasicTypeConversionTable =
    [ //                       any    long   double  bool string  date categorical
        /* Any           + */ [OpCol, OpCol, OpCol, OpCol, OpCol, OpCol, OpCol],
        /* Long          + */ [OpRow, OpCol, OpRtC, OpCtR, OpCtR, OpRtC, OpRtC],
        /* Double        + */ [OpRow, OpCtR, OpCol, OpCtR, OpCtR, OpRtC, OpNon],
        /* Boolean       + */ [OpRow, OpRtC, OpRtC, OpCol, OpCtR, OpRtC, OpNon],
        /* String        + */ [OpRow, OpRtC, OpRtC, OpRtC, OpCol, OpRtC, OpRtC],
        /* Date          + */ [OpRow, OpCtR, OpCtR, OpCtR, OpCtR, OpCol, OpNon],
        /* Categorical   + */ [OpRow, OpCtR, OpNon, OpNon, OpCtR, OpNon, OpCol],
        /* Any           - */ [OpRow, OpCol, OpCol, OpCol, OpCol, OpCol, OpCol],
        /* Long          - */ [OpRow, OpCol, OpRtC, OpCtR, OpCtR, OpRtC, OpRtC],
        /* Double        - */ [OpRow, OpCtR, OpCol, OpCtR, OpCtR, OpRtC, OpNon],
        /* Boolean       - */ [OpRow, OpRtC, OpRtC, OpCol, OpCtR, OpRtC, OpNon],
        /* String        - */ [OpRow, OpRtC, OpRtC, OpRtC, OpNon, OpRtC, OpRtC],
        /* Date          - */ [OpRow, OpCtR, OpCtR, OpCtR, OpCtR, OpCol, OpNon],
        /* Categorical   - */ [OpRow, OpCtR, OpNon, OpNon, OpCtR, OpNon, OpCol],
        /* Any           * */ [OpRow, OpCol, OpCol, OpCol, OpCol, OpCol, OpCol],
        /* Long          * */ [OpRow, OpCol, OpRtC, OpCtR, OpCtR, OpRtC, OpRtC],
        /* Double        * */ [OpRow, OpCtR, OpCol, OpCtR, OpCtR, OpRtC, OpNon],
        /* Boolean       * */ [OpRow, OpRtC, OpRtC, OpCol, OpCtR, OpRtC, OpNon],
        /* String        * */ [OpRow, OpRtC, OpRtC, OpRtC, OpNon, OpRtC, OpRtC],
        /* Date          * */ [OpRow, OpCtR, OpCtR, OpCtR, OpCtR, OpCol, OpNon],
        /* Categorical   * */ [OpRow, OpCtR, OpNon, OpNon, OpCtR, OpNon, OpCol],
        /* Any           / */ [OpRow, OpCol, OpCol, OpCol, OpCol, OpCol, OpCol],
        /* Long          / */ [OpRow, OpCol, OpRtC, OpCtR, OpCtR, OpRtC, OpRtC],
        /* Double        / */ [OpRow, OpCtR, OpCol, OpCtR, OpCtR, OpRtC, OpNon],
        /* Boolean       / */ [OpRow, OpRtC, OpRtC, OpCol, OpCtR, OpRtC, OpNon],
        /* String        / */ [OpRow, OpRtC, OpRtC, OpRtC, OpNon, OpRtC, OpRtC],
        /* Date          / */ [OpRow, OpCtR, OpCtR, OpCtR, OpCtR, OpCol, OpNon],
        /* Categorical   / */ [OpRow, OpCtR, OpNon, OpNon, OpCtR, OpNon, OpCol],
        /* Any           % */ [OpRow, OpCol, OpInt, OpInt, OpInt, OpNon, OpNon],
        /* Long          % */ [OpRow, OpCol, OpInt, OpInt, OpInt, OpNon, OpNon],
        /* Double        % */ [OpInt, OpInt, OpInt, OpInt, OpInt, OpNon, OpNon],
        /* Boolean       % */ [OpInt, OpInt, OpInt, OpInt, OpInt, OpNon, OpNon],
        /* String        % */ [OpInt, OpInt, OpInt, OpInt, OpInt, OpNon, OpNon],
        /* Date          % */ [OpNon, OpNon, OpNon, OpNon, OpNon, OpNon, OpNon],
        /* Categorical   % */ [OpNon, OpNon, OpNon, OpNon, OpNon, OpNon, OpNon]
    ];

    private readonly Dictionary<Identifier, FunctionSymbol> _functionDeclareCache = [];
    private readonly Stack<SyntaxKinds> _procedureStack = [];  // 过程类型栈，类型包括所有循环语句
    private readonly Stack<ITypeSymbol> _withSymbolStack = []; // With 语句块栈，栈顶是最近的With语句块
    private DomainSymbolTable? _currentDomain;  // 当前最近的定义域符号表
    private DomainSymbolTable? _withinDomain;   // 当前绑定的语法树所在的外部定义域符号表

    private DocumentUri? _currentUri;
    private AnalysisTree? _currentTree;
    private AnalysisTreeSymbolTable? _treeSymbolTable;

    
    /// <summary>
    /// 使用指定的符号表初始化一个语法绑定器。
    /// </summary>
    /// <param name="workFolder">指定工作文件夹</param>
    /// <param name="currentUri">当前的文件URI</param>
    /// <param name="withinDomain">外部的符号表</param>
    public static MrsBinder CreateWithinDomain(WorkFolder workFolder, DocumentUri currentUri, 
        DomainSymbolTable? withinDomain)
    {
        return new MrsBinder(workFolder)
        {
            _withinDomain = withinDomain,
            _currentUri = currentUri
        };
    }


    /// <summary>
    /// 使用<see cref="MrsBinder"/>绑定语法块中的子语句，方法不会声明函数，如果包含函数声明，
    /// 需要提前声明好放进类型是<see cref="DomainSymbolTable"/>的符号表中，传入<paramref name="withinDomain"/>
    /// 参数中。
    /// </summary>
    /// <param name="workFolder">语法文件所在的工作目录</param>
    /// <param name="block">需要进行语法绑定的语法块</param>
    /// <param name="withinDomain">已有的定义域符号表</param>
    public static AnalysisBlock BindBlockNodes(WorkFolder workFolder, Block block, DomainSymbolTable? withinDomain)
    {
        AnalysisBlock analysisBlock = AnalysisNodeFactory.Block(block, null, null);
        MrsBinder binder = CreateWithinDomain(workFolder, block.Uri, withinDomain);
        // 提前声明行标签
        foreach (var label in block.Labels)
        {
            binder.DeclareLabel(label);
        }
        // 提前声明函数
        foreach (var function in block.Functions)
        {
            binder.DeclareLocalFunction(function);
        }
        // 绑定子节点
        foreach (var statement in block.Statements)
        {
            analysisBlock.AddChild(binder.BindStatement(statement, analysisBlock));
        }
        
        return analysisBlock;
    }


    private ITypeSymbol? WithSymbol => _withSymbolStack.Count > 0 ? _withSymbolStack.Peek() : null;


    private DocumentUri CurrentUri
    {
        get
        {
            if (_currentUri != null)
            {
                return _currentUri;
            }
            
            Debug.Assert(_currentTree != null);
            return _currentTree.Syntax.Uri;
        }
    }
    

    protected override AnalysisTree BindTreeCore(SyntaxTree syntaxTree)
    {
        DocumentUri? lastUri = _currentUri;
        AnalysisTree? lastTree = _currentTree;
        DomainSymbolTable? lastDomain = _currentDomain;
        
        _currentTree = WorkFolder.GetAnalysisTree(syntaxTree);
        _treeSymbolTable = _currentTree.Symbols;
        _treeSymbolTable.Clear();
        // 如果 _currentDomain != null，则设置为语法树的父级符号表 
        if (_currentDomain != null)
        {
            _treeSymbolTable.SetParent(_currentDomain);
        }
        // 如果 lastTree 不是 null，设置语法树父级关系
        else if (lastTree != null)
        {
            _treeSymbolTable.SetParent(lastTree.Symbols);
        }
        
        // 声明 Section 的 LabelSymbol
        syntaxTree.GetLabels().ForEach(label =>
        {
            if (label.IsNode(SyntaxKinds.Label))
            {
                DeclareLabel((LabelDeclaration)label);
            }
            else
            {
                DeclareSectionLabel((SectionStatement)label);
            }
        });
        // 声明
        // 如果是入口文件语法树，提前声明函数
        if (syntaxTree.IsEntry)
        {
            syntaxTree.GetLocalFunctions().ForEach(DeclareLocalFunction);
        }
        // 绑定语句
        syntaxTree.GetNodes().ForEach(s =>
            _currentTree.AddChild(BindStatement(s, null)));

        _treeSymbolTable = null;

        // 如果是入口语法树，清空函数声明表
        if (lastTree == null && lastUri == null)
        {
            _functionDeclareCache.Clear();
        }
        
        AnalysisTree boundTree = _currentTree;
        
        _currentTree = lastTree;
        _currentUri = lastUri;
        _currentDomain = lastDomain;

        return boundTree;
    }
    
    
    private ITypeSymbol? LookupDeclaredSymbol(string fullQualifiedName)
    {
        string[] names = fullQualifiedName.Split('.');
        return
            // 1. 工作文件夹声明表
            WorkFolder.GetWorkFolderSymbolTable().LookupDeclaredSymbol(names) as ITypeSymbol ??
            // 2. 全局声明表
            GlobalSymbols.LookupDeclaredSymbol(names) as ITypeSymbol;
    }


    private ITypeSymbol? LookupDeclaredOrLocalSymbol(string name, bool lookupParent, bool lookupMetadata)
    {
        return
            // 1. 定义域
            _currentDomain?.LookupLocalSymbol(name, lookupParent) as ITypeSymbol ??
            _withinDomain?.LookupLocalSymbol(name, lookupParent) as ITypeSymbol ??
            // 2. 本地语法树符号表
            _treeSymbolTable?.LookupLocalSymbol(name) as ITypeSymbol ??
            // 3. 项目声明表和全局声明表
            WorkFolder.GetWorkFolderSymbolTable().LookupDeclaredSymbol(name) as ITypeSymbol ??
            GlobalSymbols.LookupDeclaredSymbol(name) as ITypeSymbol ??
            // 4. 本地元数据表
            (lookupMetadata ? 
                WorkFolder.GetWorkFolderSymbolTable().LookupMetadataSymbol(name) as ITypeSymbol :
                null);
    }


    private bool DeclareLocalSymbol(ITypeSymbol symbol)
    {
        if (_currentDomain != null)
        {
            return _currentDomain.DeclareSymbol(symbol);
        }

        if (_withinDomain != null)
        {
            return _withinDomain.DeclareSymbol(symbol);
        }

        return _treeSymbolTable != null && _treeSymbolTable.DeclareSymbol(symbol);
    }


    private ITypeSymbol? LookupOrDeclareLocalSymbol(Identifier id, ISymbol? context,
        bool allowDeclareImplicitly)
    {
        // 查找类型符号的成员名或函数名
        ITypeSymbol? symbol =
            // 1. 查找上下文符号的成员名
            (context as ITypeSymbol)?.GetNamedMember(id.Value) ??
            // 2. 查找本地变量，优先本地符号表
            LookupDeclaredOrLocalSymbol(id.Value, 
                id.GetFlags(SyntaxNodeFlags.OptionGlobalVariables),
                id.GetFlags(SyntaxNodeFlags.OnNextCaseEvent));

        // 如果查找到的是模块或接口，忽略
        if (symbol is { IsModule: true } or { IsInterface: true })
        {
            symbol = null;
        }

        // 如果找到的是类，检查是否带有常量，如果不带有常量，则类名不作为标识符绑定类型。
        if (symbol is { IsClass: true, WithConstant: false })
        {
            symbol = null;
        }

        if (symbol != null || !allowDeclareImplicitly || !id.GetFlags(SyntaxNodeFlags.OptionImplicit))
        {
            return symbol;
        }

        VariableDeclaration declaration = NodeFactory.CreateVariableDeclaration(null, id);
        declaration.UpdateFrom(id);
        symbol = new LocalSymbol(declaration);
        DeclareLocalSymbol(symbol);

        return symbol;
    }


    private void BindCategory(AnalysisIdentifier? bound, MetadataFieldSymbol field)
    {
        bound?.WithContainingWithSymbol(WithSymbol);

        if (bound == null)
        {
            return;
        }

        if (field.LookupCategory(bound.Text) is { } categorySymbol)
        {
            bound.Bind((MetadataCategorySymbol)categorySymbol);
        }
        else
        {
            Raise(DiagnosticDescriptors.UnknownMetadataCategory, bound.Syntax, bound.Text);
        }
    }


    private static int GetIndexBoundary(IndexExpression expression)
    {
        int boundary = 1;
        var expr = expression.Parent as IndexExpression;

        while (expr != null)
        {
            boundary++;
            expr = expr.Parent as IndexExpression;
        }

        return boundary;
    }


    private AnalysisExpression BindString(StringLiteral literal, ISymbol? contextSymbol, AnalysisNode? parent)
    {
        AnalysisString str = AnalysisNodeFactory.String(literal, parent);

        if (contextSymbol is not { IsMetadataField: true })
        {
            return str;
        }

        MetadataFieldSymbol field = (MetadataFieldSymbol)contextSymbol;

        // 如果是数字，检查上下限
        AnalysisExpression? convert = str.WithImplicitlyConversion(ValueTypeSymbol.Long);
        if (convert != null)
        {
            AnalysisInteger convertedInteger = (AnalysisInteger)convert;

            if (convertedInteger.Value < 0 || convertedInteger.Value >= field.CategoriesCount)
            {
                Raise(DiagnosticDescriptors.MetadataFieldIndexOutOfRange, literal, field.FullName);
            }

            return convertedInteger;
        }

        // 如果是标识符，查找同名分类名
        if (StringHelper.IsValidIdentifier(str.Value))
        {
            if (field.LookupCategory(str.Value) is { } categorySymbol)
            {
                str.Bind(categorySymbol);
            }
            else
            {
                Raise(DiagnosticDescriptors.UnknownMetadataCategory, literal, field.FullName);
            }

            return str;
        }

        // 如果是分类值，查找分类名
        AnalysisExpression? categorical = str.WithImplicitlyConversion(ValueTypeSymbol.Categorical);
        if (categorical != null)
        {
            bool isValid = categorical.ChildrenCount == 1;
            categorical.ForEachChild(e =>
            {
                AnalysisCategory category = (AnalysisCategory)e;
                if (category.IsRange)
                {
                    isValid = false;
                }

                BindCategory(category.RangeLeft, field);
                BindCategory(category.RangeRight, field);
            });

            if (!isValid)
            {
                Raise(DiagnosticDescriptors.InvalidIndex, literal);
            }

            return categorical;
        }

        Raise(DiagnosticDescriptors.UnexpectedToken, literal, "整数、字符串或分类常量");
        return str;
    }


    private AnalysisCategorical BindCategorical(CategoricalLiteral literal, ISymbol? contextSymbol,
        AnalysisNode? parent)
    {
        AnalysisCategorical categorical = AnalysisNodeFactory.Categorical(literal, parent);

        if (contextSymbol is not { IsMetadataField: true })
        {
            return categorical;
        }

        MetadataFieldSymbol field = (MetadataFieldSymbol)contextSymbol;
        // 检查分类名
        categorical.ForEachChild(e =>
        {
            AnalysisCategory category = (AnalysisCategory)e;
            BindCategory(category.RangeLeft, field);
            BindCategory(category.RangeRight, field);
        });

        return categorical;
    }


    private AnalysisIdentifier BindIdentifier(Identifier identifier, ISymbol? contextSymbol,
        AnalysisNode? parent)
    {
        // Object.Member,Identifier(),Identifier[] 不允许隐式声明
        bool canDeclareImplicitly = identifier.Parent?.IsOneOfNode(
            SyntaxKinds.MemberExpression, SyntaxKinds.IndexExpression, SyntaxKinds.CallExpression) != true;

        AnalysisIdentifier localId = AnalysisNodeFactory.Identifier(identifier, parent, WithSymbol);
        ITypeSymbol? boundSymbol = LookupOrDeclareLocalSymbol(identifier, contextSymbol, canDeclareImplicitly);

        // 查询集合类型的绑定成员类型：
        // 如果Collection是一个集合，List是Collection类型的变量，那么，
        // 表达式List.Item1中的Item1表示添加一个名为'Item1'的成员对象到集合或者访问已有的同名成员。
        if (boundSymbol == null && contextSymbol is ITypeSymbol typeSymbol)
        {
            ITypeSymbol? indexerSymbol = typeSymbol.GetIndexer();
            if (indexerSymbol != null)
            {
                boundSymbol = indexerSymbol.GetBindableBindingOrThis();
            }
        }

        localId.Bind(boundSymbol ?? ValueTypeSymbol.Any);
        return localId;
    }


    private AnalysisMemberExpression BindMember(MemberExpression memberExpression, ISymbol? contextSymbol,
        AnalysisNode? parent)
    {
        AnalysisExpression? memberObjExpr = null;
        ITypeSymbol memberContext;

        if (memberExpression.Object.IsEmpty)
        {
            memberContext = contextSymbol as ITypeSymbol ?? WithSymbol ?? ValueTypeSymbol.Any;
        }
        else
        {
            memberObjExpr = BindExpression(memberExpression.Object, contextSymbol, null);
            memberContext = memberObjExpr.GetTypeSymbol();
        }

        AnalysisIdentifier memberExpr = BindIdentifier(memberExpression.Member,
            memberContext.GetFinalBindableBindingOrThis(),
            null);

        AnalysisMemberExpression expressionNode = AnalysisNodeFactory.MemberExpression(memberExpression,
                memberObjExpr, memberExpr, parent, WithSymbol);
        expressionNode.Bind(memberExpr.GetTypeSymbol());
        return expressionNode;
    }


    private AnalysisIndexExpression BindIndex(IndexExpression indexSyntax, ISymbol? contextSymbol,
        AnalysisNode? parent)
    {
        AnalysisIndexExpression indexExpression = AnalysisNodeFactory.Index(indexSyntax, null, parent, WithSymbol);
        AnalysisExpression objExpression = BindExpression(indexSyntax.Object, contextSymbol, indexExpression);
        indexExpression.SetObject(objExpression);

        ITypeSymbol objSymbol = objExpression.GetTypeSymbol();
        ITypeSymbol? indexer = objSymbol.LookupIndexerOrPropertyWithParameters();
        // 没有找到索引器时，检查最终返回类型
        if (indexer is null)
        {
            objSymbol = objSymbol.GetFinalBindableBindingOrThis();
            // Any | Undefined
            if (ValueTypeSymbol.IsAnyOrNull(objSymbol) || objSymbol.IsUndefined)
            {
                indexExpression.Bind(objSymbol);
                return indexExpression;
            }

            // 非 Categorical 或 数组
            if (objSymbol is { IsArray: false, IsArrayType: false } && !ValueTypeSymbol.IsCategorical(objSymbol))
            {
                Raise(DiagnosticDescriptors.TypeHasNoIndexer, indexSyntax.Object, objSymbol.FullName);
                indexExpression.Bind(objSymbol);
                return indexExpression;
            }

            indexer = objSymbol;
        }

        // Array[] -> 本地符号 array[] 声明成绑定类型 any[]
        if (indexer.IsArrayType)
        {
            indexExpression.Bind(BindArrayTypeIndex(indexExpression, indexer));
        }
        // Categorical
        else if (ValueTypeSymbol.IsCategorical(indexer))
        {
            indexExpression.Bind(ValueTypeSymbol.Any);
            // 只允许有一个数字索引，并且需要大于等于0.
            BindNumericIndexArguments(indexExpression);
            if (indexSyntax.Arguments?.Count > 1)
            {
                Raise(DiagnosticDescriptors.ArrayIndexAccessorCanOnlyHaveOnArgument, indexSyntax.Arguments);
            }
        }
        else
        {
            // 绑定到最终的默认属性类型
            indexExpression.Bind(indexer.GetFinalBindableBindingOrThis());
            // 检查参数
            BindArguments(indexExpression, indexSyntax.Arguments, indexer);
        }

        return indexExpression;
    }


    private void BindNumericIndexArguments(AnalysisIndexExpression indexExpression)
    {
        IndexExpression syntax = indexExpression.Syntax;
        if (syntax.Arguments == null || syntax.Arguments.Count == 0)
        {
            Raise(DiagnosticDescriptors.MissingArrayIndex, syntax.Arguments as ITextNode ?? syntax);
        }
        else
        {
            syntax.Arguments.ForEach(argExpression =>
            {
                AnalysisExpression boundExpression = BindExpression(argExpression, null, indexExpression);

                if (boundExpression is AnalysisInteger { Value: < 0 })
                {
                    Raise(DiagnosticDescriptors.InvalidIndex, argExpression);
                }

                // 首先检查返回的类型是否可以赋值给Long类型
                if (ValueTypeSymbol.Long.IsAssignableFrom(boundExpression.GetTypeSymbol()))
                {
                    return;
                }

                AnalysisExpression? conversion = boundExpression.WithImplicitlyConversion(ValueTypeSymbol.Long);
                if (conversion == null)
                {
                    // 不是常量时，查找表达式的最终类型
                    var valueSymbol = boundExpression.GetTypeSymbol().GetFinalBindableBindingOrThis();
                    // 检查和Long类型的匹配性
                    if (!ValueTypeSymbol.Long.IsAssignableFrom(valueSymbol) &&
                        !ValueTypeSymbol.IsAnyOrNull(valueSymbol) && !valueSymbol.IsUndefined)
                    {
                        Raise(DiagnosticDescriptors.CannotConvertTypeImplicitly, argExpression,
                            valueSymbol.FullName, "Long");
                    }
                    else
                    {
                        // 更新绑定类型
                        boundExpression.Bind(valueSymbol);
                    }
                    
                    indexExpression.AddChild(boundExpression);
                }
                else
                {
                    indexExpression.AddChild(conversion);
                    // 索引值如果是数字常量，需要大于等于0.
                    if (boundExpression is AnalysisInteger { Value: < 0 })
                    {
                        Raise(DiagnosticDescriptors.InvalidIndex, argExpression);
                    }
                }
            });
        }
    }


    private ITypeSymbol BindArrayTypeIndex(AnalysisIndexExpression indexExpression, ITypeSymbol symbol)
    {
        Debug.Assert(symbol.IsArrayType);
        ArrayTypeSymbol local = (ArrayTypeSymbol)symbol;
        IndexExpression syntax = indexExpression.Syntax;
        int indexBound = GetIndexBoundary(syntax);

        if (syntax.Arguments == null || syntax.Arguments.Count == 0)
        {
            Raise(DiagnosticDescriptors.MissingArrayIndex, syntax.Arguments as ITextNode ?? syntax);
        }
        else
        {
            BindNumericIndexArguments(indexExpression);

            if (syntax.Arguments?.Count > 1)
            {
                Raise(DiagnosticDescriptors.ArrayIndexAccessorCanOnlyHaveOnArgument, syntax);
            }
        }

        return indexBound < local.Rank
            // 如果索引维度小于定义维度，缩减维度数
            ? local.OriginalDefinition.MakeArrayType(local.Rank - indexBound, null)
            // 如果索引维度大于等于定义维度，返回原始类型
            : local.OriginalDefinition;
    }


    private AnalysisCallExpression BindCall(CallExpression callExpression, ISymbol? contextSymbol,
        AnalysisNode? parent)
    {
        AnalysisCallExpression callExpr = AnalysisNodeFactory.CallExpression(callExpression, parent, WithSymbol);
        AnalysisExpression caller = BindExpression(callExpression.Callee, contextSymbol, callExpr);
        callExpr.SetCallee(caller);
        BindArguments(callExpr, callExpression.Arguments, caller.GetTypeSymbol());
        // CreateObject
        bool isCreateObjectBound = false;
        if (caller.IsIdentifier &&
            ((AnalysisIdentifier)caller).Syntax.Value.Equals("CreateObject", StringComparison.OrdinalIgnoreCase) &&
            callExpr.ChildrenCount == 2)
        {
            AnalysisExpression objectName = callExpr.GetArgumentAt(0);
            // String
            if (objectName.IsString)
            {
                string typeFullName = ((AnalysisString)objectName).Value;
                ITypeSymbol? declared = LookupDeclaredSymbol(typeFullName);

                if (declared != null)
                {
                    callExpr.Bind(declared);
                    isCreateObjectBound = true;
                }
                else
                {
                    Raise(DiagnosticDescriptors.UnknownTypeFullName, objectName.Syntax, typeFullName);
                }
            }
        }

        if (!isCreateObjectBound)
        {
            callExpr.Bind(caller.GetTypeSymbol().GetBindableBindingOrThis());
        }

        return callExpr;
    }


    /// <summary>
    ///     单目运算符有两种：Not和'-'，其中，
    ///     '-'表示负数，需要后续表达式可以隐式转换为<seealso cref="ValueTypeSymbol.Long" />。
    ///     Not后的表达式类型需要能够隐式转换为<see cref="ValueTypeSymbol.Boolean" />。
    /// </summary>
    /// <param name="unaryExpression">一元表达式</param>
    /// <param name="contextSymbol">当前上下文符号</param>
    /// <param name="parent">表达式的父节点</param>
    /// <returns>
    ///     一元表达式的返回类型可能是<see cref="ValueTypeSymbol.Long" />、
    ///     <see cref="ValueTypeSymbol.Double" />、<see cref="ValueTypeSymbol.Boolean" />或
    ///     <see cref="ValueTypeSymbol.Any" />
    /// </returns>
    private AnalysisUnary BindUnary(UnaryExpression unaryExpression, ISymbol? contextSymbol,
        AnalysisNode? parent)
    {
        AnalysisExpression expr = BindExpression(unaryExpression.Expression, contextSymbol, null);
        AnalysisUnary unary = AnalysisNodeFactory.Unary(unaryExpression, parent, WithSymbol, expr);

        if (unaryExpression.Operator.IsNode(SyntaxKinds.MinusToken))
        {
            // -
            ITypeSymbol exprSymbol = expr.GetTypeSymbol();
            // Long | Any
            if (ReferenceEquals(exprSymbol, ValueTypeSymbol.Any) ||
                ReferenceEquals(exprSymbol, ValueTypeSymbol.Long))
            {
                unary.Bind(ValueTypeSymbol.Long);
            }
            // Double
            else if (ReferenceEquals(exprSymbol, ValueTypeSymbol.Double))
            {
                unary.Bind(ValueTypeSymbol.Double);
            }
            // Error
            else
            {
                Raise(DiagnosticDescriptors.TypeDoesNotSupportNegativeOperator, unaryExpression.Expression,
                    exprSymbol.FullName);
            }
        }
        else
        {
            // Not
            unary.Bind(ValueTypeSymbol.Boolean);
        }

        return unary;
    }


    /// <summary>
    ///     绑定参数调用表达式的参数符号，同时检查参数表达式和符号是否和定义类型兼容。
    /// </summary>
    /// <param name="callerExpr">分析树表达式</param>
    /// <param name="arguments">调用参数列表</param>
    /// <param name="contextSymbol">上下文符号</param>
    private void BindArguments(AnalysisExpression callerExpr, ArgumentList? arguments, ITypeSymbol contextSymbol)
    {
        int startIndex = 0;

        // 区分是索引表达式的参数列表或是函数调用表达式的参数列表
        AnalysisExpression caller = callerExpr.BoundKind == AnalysisBoundKinds.Index
            ? ((AnalysisIndexExpression)callerExpr).GetObject()
            : ((AnalysisCallExpression)callerExpr).GetCallee();
        
        IReadOnlyList<ParameterSymbol> parameterSymbols = new List<ParameterSymbol>();
        BindableSymbolWithParameters? bindableSymbol = null;

        if (contextSymbol is not { WithParameter: true })
        {
            // 需要额外注意，如果查询到的是LocalSymbol，并且通过成员表达式调用，视为 Any 类型。
            if (contextSymbol is { IsLocalVariable: true } &&
                callerExpr is AnalysisIndexExpression { Object.BoundKind: AnalysisBoundKinds.Member }
                    or AnalysisCallExpression { Callee.BoundKind: AnalysisBoundKinds.Member })
            {
                AnalysisMemberExpression member =
                    callerExpr is AnalysisIndexExpression { Object.BoundKind: AnalysisBoundKinds.Member } index
                        ? (AnalysisMemberExpression)index.GetObject()
                        : (AnalysisMemberExpression)((AnalysisCallExpression)callerExpr).GetCallee();
                
                member.Bind(ValueTypeSymbol.Any);
                member.Member.Bind(ValueTypeSymbol.Any);
                
                // 移除之前的绑定
                contextSymbol.RemoveReference(member.Member.Syntax.GetLocation());
                contextSymbol.RemoveReference(member.Syntax.GetLocation());
            }
            // 非 Any， Null 或 Undefined 类型时，报告错误。
            else if (contextSymbol is not { IsUndefined: true } && !ValueTypeSymbol.IsAnyOrNull(contextSymbol))
            {
                Raise(
                    callerExpr is { BoundKind: AnalysisBoundKinds.Index }
                        ? DiagnosticDescriptors.PropertyWithNoParameters
                        : DiagnosticDescriptors.IsNotFunctionOrMethod,
                    caller.Syntax,
                    contextSymbol.FullName);
            }
        }
        else
        {
            bindableSymbol = (BindableSymbolWithParameters)contextSymbol;
            parameterSymbols = bindableSymbol.Parameters;

            if (caller is { BoundKind: AnalysisBoundKinds.Member } && 
                bindableSymbol is { IsMethod: false, IsProperty: false })
            {
                startIndex = 1;
                // 检查第一个参数和类型和调用方的符号类型
                ITypeSymbol callerSymbol = caller.GetTypeSymbol();
                if (parameterSymbols.Count > 0 &&
                    !CheckTypeCompatible(callerSymbol, parameterSymbols[0]))
                {
                    Raise(DiagnosticDescriptors.UnmatchedType, callerExpr.Syntax,
                        callerSymbol.FullName, parameterSymbols[0].FullName);
                }
            }
        }

        if (arguments != null)
        {
            int parameterIndex = 0;
            for (int i = startIndex; i < arguments.Count; i++)
            {
                AnalysisExpression argExpr = BindExpression(arguments[i], contextSymbol, null);
                callerExpr.AddChild(argExpr);

                if (parameterIndex >= parameterSymbols.Count)
                {
                    continue;
                }

                // 检查类型兼容性
                argExpr.Bind(CheckTypeCompatible(argExpr,
                    parameterSymbols[parameterIndex].GetFinalDefaultPropertyBindingOrThis()));
                parameterIndex++;
            }
        }

        if (bindableSymbol != null &&
            !bindableSymbol.CanAcceptParameters((arguments?.Count ?? 0) + startIndex))
        {
            Raise(DiagnosticDescriptors.UnmatchedParameterLength,
                arguments as ITextNode ?? callerExpr.Syntax,
                contextSymbol.FullName,
                bindableSymbol.ParametersCount,
                (arguments?.Count ?? 0) + startIndex);
        }
    }

    // 1 Only if conversion from text to numeric is possible.
    // 2 Operation occurs on the date's double value representation.
    //   If the operation involves an invalid date, '####' is returned.
    // 3 Only if conversion from text to long or categorical is possible.
    // 4 Only if conversion from text to date is possible.
    // 5 If the text can be converted to a long without loss of precision, the result is a long.
    //
    //  + Operator
    //  +-------------+-----------------+-------------------+----------------------+----------------------+----------------+
    //  |             | Double          | Long              | Text                 | Categorical          | Date           |
    //  +-------------+-----------------+-------------------+----------------------+----------------------+----------------+
    //  | Double      | Add Double      | Add Double        | Add(1) Double        | Not applicable       | Add(2) Date    |
    //  +-------------+-----------------+-------------------+----------------------+----------------------+----------------+
    //  | Long        | Add Double      | Add Long          | Add(1) Long          | Union Categorical    | Add(2) Date    |
    //  +-------------+-----------------+-------------------+----------------------+----------------------+----------------+
    //  | Text        | Add(1) Double   | Add(1) Double(5)  | Concatenation Text   | Union(3) Categorical | Add(4) Date    |
    //  +-------------+-----------------+-------------------+----------------------+----------------------+----------------+
    //  | Categorical | Not applicable  | Union Categorical | Union(3) Categorical | Union Categorical    | Not applicable |
    //  +-------------+-----------------+-------------------+----------------------+----------------------+----------------+
    //  | Date        | Add(2) Date     | Add(2) Date       | Add(4) Date          | Not applicable       | Add Date       |
    //  +-------------+-----------------+-------------------+----------------------+----------------------+----------------+
    //
    //  - Operator
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  |             | Double             | Long                 | Text                     | Categorical             | Date             |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  | Double      | Subtract Double    | Subtract Double      | Subtract(1) Double       | Not applicable          | Subtract(2) Date |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  | Long        | Subtract Double    | Subtract Long        | Subtract(1) Long         | Subtract Categorical    | Subtract(2) Date |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  | Text        | Subtract(1) Double | Subtract(4) Double(5)| Not applicable           | Subtract(3) Categorical | Subtract(4) Date |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  | Categorical | Not applicable     | Subtract Categorical | Subtract(3) Categorical  | Subtract Categorical    | Not applicable   |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  | Date        | Subtract(2) Date   | Subtract(2) Date     | Subtract(4) Date         | Not applicable          | Subtract Date    |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //
    //  * Operator
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  |             | Double             | Long                 | Text                     | Categorical             | Date             |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  | Double      | Multiply Double    | Multiply Double      | Multiply(1) Double       | Not applicable          | Multiply(2) Date |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  | Long        | Multiply Double    | Multiply Long        | Multiply(1) Long         | Intersect Categorical   | Multiply(2) Date |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  | Text        | Multiply(1) Double | Multiply(4) Double(5)| Not applicable           | Intersect(3) Categorical| Multiply(4) Date |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  | Categorical | Not applicable     | Intersect Categorical| Intersect(3) Categorical | Intersect Categorical   | Not applicable   |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //  | Date        | Multiply(2) Date   | Multiply(2) Date     | Multiply(4) Date         | Not applicable          | Multiply Date    |
    //  +-------------+--------------------+----------------------+--------------------------+-------------------------+------------------+
    //
    //  / Operator
    //  +-------------+--------------------+------------------------+--------------------------+---------------------------+------------------+
    //  |             | Double             | Long                   | Text                     | Categorical               | Date             |
    //  +-------------+--------------------+------------------------+--------------------------+---------------------------+------------------+
    //  | Double      | Divide Double      | Divide Double          | Divide(1) Double         | Not applicable            | Divide(2) Date   |
    //  +-------------+--------------------+------------------------+--------------------------+---------------------------+------------------+
    //  | Long        | Divide Double      | Divide Long            | Divide(1) Long           | Difference Categorical    | Divide(2) Date   |
    //  +-------------+--------------------+------------------------+--------------------------+---------------------------+------------------+
    //  | Text        | Divide(1) Double   | Divide(4) Double(5)    | Not applicable           | Difference(3) Categorical | Divide(4) Date   |
    //  +-------------+--------------------+------------------------+--------------------------+---------------------------+------------------+
    //  | Categorical | Not applicable     | Difference Categorical | Difference(3) Categorical| Difference Categorical    | Not applicable   |
    //  +-------------+--------------------+------------------------+--------------------------+---------------------------+------------------+
    //  | Date        | Divide(2) Date     | Divide(2) Date         | Divide(4) Date           | Not applicable            | Divide Date      |
    //  +-------------+--------------------+------------------------+--------------------------+---------------------------+------------------+


    private static int GetConversionIndex(ITypeSymbol typeSymbol)
    {
        return typeSymbol.Name switch
        {
            "Any" or "Null" or "Undefined" => Any,
            "Long" => Int,
            "Double" => Dbl,
            "Boolean" => Bln,
            "String" => Str,
            "Date" => Dat,
            "Categorical" => Cat,
            _ => -1
        };
    }


    private static bool IsArithmeticOperator(SyntaxKinds kind)
    {
        return kind is SyntaxKinds.PlusToken or SyntaxKinds.MinusToken or SyntaxKinds.AsteriskToken
            or SyntaxKinds.SlashToken or SyntaxKinds.ModKeywordToken;
    }


    private static int GetArithmeticOperatorIndex(SyntaxKinds kind)
    {
        Debug.Assert(IsArithmeticOperator(kind));

        return kind switch
        {
            SyntaxKinds.PlusToken => OpAdd,
            SyntaxKinds.MinusToken => OpSubtract,
            SyntaxKinds.AsteriskToken => OpMultiply,
            SyntaxKinds.SlashToken => OpDivide,
            SyntaxKinds.ModKeywordToken => OpModulo,
            _ => -1
        };
    }


    private static int GetConversionRowIndex(SyntaxKinds operatorKind, ITypeSymbol symbol)
    {
        Debug.Assert(IsArithmeticOperator(operatorKind) || SyntaxFacts.IsCompareOperatorUnchecked(operatorKind));

        if (SyntaxFacts.IsCompareOperatorUnchecked(operatorKind))
        {
            // 和加法的转换相同
            operatorKind = SyntaxKinds.PlusToken;
        }

        int index = GetArithmeticOperatorIndex(operatorKind);
        return index == -1 ? -1 : (index * 7) + GetConversionIndex(symbol);
    }


    private static int GetArithmeticOrCompareOperation(SyntaxKinds operatorKind, ITypeSymbol rowSymbol,
        ITypeSymbol colSymbol)
    {
        int rowIndex = GetConversionRowIndex(operatorKind, rowSymbol);
        int colIndex = GetConversionIndex(colSymbol);

        if (rowIndex == -1 || colIndex == -1)
        {
            return -1;
        }

        return BasicTypeConversionTable[rowIndex][colIndex];
    }


    private AnalysisBinary BindBinary(BinaryExpression binary, ISymbol? contextSymbol, AnalysisNode? parent)
    {
        AnalysisExpression leftExpr = BindExpression(binary.LeftOperand, contextSymbol, null);
        AnalysisExpression rightExpr = BindExpression(binary.RightOperand, contextSymbol, null);

        ITypeSymbol leftSymbol = leftExpr.GetTypeSymbol().GetFinalDefaultPropertyBindingOrThis();
        ITypeSymbol rightSymbol = rightExpr.GetTypeSymbol().GetFinalDefaultPropertyBindingOrThis();

        AnalysisExpression? convertedLeftExpr = null;
        AnalysisExpression? convertedRightExpr = null;

        ITypeSymbol binaryReturnType = ValueTypeSymbol.Any;

        // Arithmetic Operator
        if (IsArithmeticOperator(binary.OperatorToken.Kind) ||
            SyntaxFacts.IsCompareOperatorUnchecked(binary.OperatorToken.Kind))
        {
            int arithmeticOperation = GetArithmeticOrCompareOperation(binary.OperatorToken.Kind,
                leftSymbol, rightSymbol);

            switch (arithmeticOperation)
            {
                // 转换到Long
                case OpInt:
                {
                    binaryReturnType = ValueTypeSymbol.Long;
                    convertedLeftExpr = leftExpr.WithImplicitlyConversion(ValueTypeSymbol.Long);
                    convertedRightExpr = rightExpr.WithImplicitlyConversion(ValueTypeSymbol.Long);

                    if (convertedLeftExpr == null || convertedRightExpr == null)
                    {
                        goto default;
                    }

                    break;
                }

                // 行->列
                case OpRtC:
                {
                    binaryReturnType = rightSymbol.IsUndefined ? ValueTypeSymbol.Any : (ValueTypeSymbol)rightSymbol;
                    convertedLeftExpr = leftExpr.WithImplicitlyConversion((ValueTypeSymbol)binaryReturnType);

                    if (convertedLeftExpr == null)
                    {
                        goto default;
                    }

                    break;
                }

                // 列->行
                case OpCtR:
                {
                    binaryReturnType = leftSymbol.IsUndefined ? ValueTypeSymbol.Any : (ValueTypeSymbol)leftSymbol;
                    convertedRightExpr = rightExpr.WithImplicitlyConversion((ValueTypeSymbol)binaryReturnType);

                    if (convertedRightExpr == null)
                    {
                        goto default;
                    }

                    break;
                }

                // 列无需转换
                case OpRow:
                {
                    binaryReturnType = leftSymbol;
                    break;
                }

                // 行无需转换
                case OpCol:
                {
                    binaryReturnType = rightSymbol;
                    break;
                }

                default:
                {
                    Raise(DiagnosticDescriptors.CannotApplyOperation, binary,
                        SyntaxFacts.ConvertTokenToString(binary.OperatorToken.Kind), leftSymbol.FullName,
                        rightSymbol.FullName);
                    break;
                }
            }
        }
        // Logical operator
        else if (SyntaxFacts.IsLogicalOperatorUnchecked(binary.OperatorToken.Kind))
        {
            // 一般情况下，所有类型的表达式都可以转换为Boolean值
            binaryReturnType = ValueTypeSymbol.Boolean;
        }
        // Is
        else if (binary.OperatorToken.IsNode(SyntaxKinds.IsKeywordToken))
        {
            // Is [Not] Null
            if (!binary.RightOperand.IsNode(SyntaxKinds.Null) &&
                !(binary.RightOperand.Is<UnaryExpression>(SyntaxKinds.UnaryExpression,
                      out UnaryExpression? rightUnary) &&
                  rightUnary.Operator.IsNode(SyntaxKinds.NotKeywordToken) &&
                  rightUnary.Expression.IsNode(SyntaxKinds.Null)))
            {
                Raise(DiagnosticDescriptors.UnexpectedToken, binary.RightOperand,
                    "Null 或 Not Null");
            }

            binaryReturnType = ValueTypeSymbol.Boolean;
        }
        // Like
        else if (binary.OperatorToken.IsNode(SyntaxKinds.LikeKeywordToken))
        {
            // "String" Like "Pattern_string"
            ExpectAnyOrString(binary.LeftOperand, leftSymbol);
            ExpectAnyOrString(binary.RightOperand, rightSymbol);

            binaryReturnType = ValueTypeSymbol.Boolean;
        }

        AnalysisBinary binaryExpr = AnalysisNodeFactory.Binary(binary, parent, 
            convertedLeftExpr ?? leftExpr,
            convertedRightExpr ?? rightExpr, 
            WithSymbol);

        binaryExpr.Bind(binaryReturnType);
        return binaryExpr;

        void ExpectAnyOrString(Expression expression, ITypeSymbol symbol)
        {
            if (ValueTypeSymbol.IsAnyOrNull(symbol) || symbol.IsUndefined || ValueTypeSymbol.IsString(symbol))
            {
                return;
            }

            Raise(DiagnosticDescriptors.UnexpectedToken, expression, "字符串");
        }
    }


    private AnalysisAssignment BindAssignment(AssignmentExpression expression, ISymbol? contextSymbol,
        AnalysisNode? parent)
    {
        AnalysisExpression leftExpression = BindExpression(expression.LeftOperand, contextSymbol, null);
        AnalysisExpression rightExpression = BindExpression(expression.RightOperand, contextSymbol, null);

        ITypeSymbol leftSymbol = leftExpression.GetTypeSymbol();
        ITypeSymbol rightSymbol = rightExpression.GetTypeSymbol();

        // 左值只读
        if (leftSymbol.IsReadOnly)
        {
            Raise(DiagnosticDescriptors.SymbolIsReadonly, expression.LeftOperand, leftSymbol.FullName);
        }
        // 右值只写
        else if (rightSymbol.IsWriteOnly)
        {
            Raise(DiagnosticDescriptors.SymbolIsWriteOnly, expression.RightOperand, rightSymbol.FullName);
        }
        // 右值返回Void
        else if (rightExpression.BoundKind == AnalysisBoundKinds.Call &&
                 (((AnalysisCallExpression)rightExpression).GetCallee()).GetTypeSymbol() is { } callerSymbol &&
                 ValueTypeSymbol.IsVoid(callerSymbol.GetBindableBindingOrThis()))
        {
            Raise(DiagnosticDescriptors.FunctionOrMethodHasNoReturnValue, expression.RightOperand, 
                callerSymbol.FullName);
        }
        else
        {
            ITypeSymbol resultSymbol = rightExpression.GetTypeSymbol();
            switch (leftSymbol)
            {
                // 如果是本地符号，更新绑定类型
                // 本地非数组变量
                case { IsLocalVariable: true, IsArray: false }:
                {
                    LocalSymbol local = (LocalSymbol)leftSymbol;
                    local.UpdateBindingSymbol(CurrentUri, expression.Start,
                        local.IsFunctionReturnSymbol ? rightSymbol.MakeUnion(local.GetBindingSymbol()) : resultSymbol);

                    break;
                }
                // 本地数组，检查绑定的数组类型是否和当前的类型相同，如果不相同，更新为Union类型的数组。
                case { IsLocalVariable: true, IsArray: true } when 
                    !leftSymbol.OriginalDefinition.Equals(resultSymbol):
                {
                    LocalSymbol localArray = (LocalSymbol)leftSymbol;
                    ArrayTypeSymbol leftBindable = (ArrayTypeSymbol)localArray.BindingSymbol;
                    // 如果当前类型是Any，更新为右值类型
                    if (leftSymbol.OriginalDefinition.Equals(ValueTypeSymbol.Any))
                    {
                        ((LocalSymbol)leftSymbol).UpdateBindingSymbol(CurrentUri, expression.Start, resultSymbol);
                    }
                    else
                    {
                        ((LocalSymbol)leftSymbol).UpdateBindingSymbol(CurrentUri, expression.Start,
                            resultSymbol.MakeUnion((ITypeSymbol)leftSymbol.OriginalDefinition)
                                .MakeArrayType(leftBindable.Rank, leftBindable.GetBoundaries()));
                    }

                    break;
                }
            }
        }

        return AnalysisNodeFactory.Assignment(expression, leftExpression, rightExpression, parent, WithSymbol);
    }


    private static bool CheckTypeCompatible(ITypeSymbol from, ITypeSymbol to)
    {
        ITypeSymbol finalBindableSymbol = from.GetFinalDefaultPropertyBindingOrThis();
        return ValueTypeSymbol.IsAnyOrNull(finalBindableSymbol) || ValueTypeSymbol.IsAnyOrNull(to) ||
               ReferenceEquals(finalBindableSymbol, to) || ReferenceEquals(finalBindableSymbol, to) ||
               to.IsAssignableFrom(finalBindableSymbol);
    }


    private ITypeSymbol CheckTypeCompatible(AnalysisExpression sourceExpression, ITypeSymbol targetType)
    {
        ITypeSymbol exprSymbol = sourceExpression.GetTypeSymbol().GetFinalDefaultPropertyBindingOrThis();

        if (CheckTypeCompatible(exprSymbol, targetType))
        {
            return exprSymbol;
        }

        if (targetType is { IsValueType: true } &&
            sourceExpression.WithImplicitlyConversion((ValueTypeSymbol)targetType) != null)
        {
            return targetType;
        }

        Raise(DiagnosticDescriptors.CannotConvertTypeImplicitly, sourceExpression.Syntax,
            exprSymbol.FullName, targetType.FullName);

        return targetType;
    }


    private AnalysisEmptyExpression BindObjectIteration(ObjectCollectionIteration iteration)
    {
        Raise(DiagnosticDescriptors.OnlyMetadataFieldCanUseObjectIterator, iteration);
        return AnalysisNodeFactory.EmptyExpression(null);
    }


    private AnalysisExpression BindExpression(Expression expression, ISymbol? contextSymbol,
        AnalysisNode? parent)
    {
        return expression.Kind switch
        {
            // Literal
            SyntaxKinds.String => BindString((StringLiteral)expression, contextSymbol, parent),
            SyntaxKinds.Integer => new AnalysisInteger((IntegerLiteral)expression, parent),
            SyntaxKinds.Double => new AnalysisDouble((DoubleLiteral)expression, parent),
            SyntaxKinds.Boolean => new AnalysisBoolean((BooleanLiteral)expression, parent),
            SyntaxKinds.Categorical => BindCategorical((CategoricalLiteral)expression, contextSymbol, parent),
            SyntaxKinds.Null => new AnalysisNull((NullLiteral)expression, parent),

            // Expression
            SyntaxKinds.Identifier => BindIdentifier((Identifier)expression, contextSymbol, parent),
            SyntaxKinds.MemberExpression => BindMember((MemberExpression)expression, contextSymbol, parent),
            SyntaxKinds.IndexExpression => BindIndex((IndexExpression)expression, contextSymbol, parent),
            SyntaxKinds.CallExpression => BindCall((CallExpression)expression, contextSymbol, parent),
            SyntaxKinds.UnaryExpression => BindUnary((UnaryExpression)expression, contextSymbol, parent),
            SyntaxKinds.BinaryExpression => BindBinary((BinaryExpression)expression, contextSymbol, parent),
            SyntaxKinds.AssignmentExpression => BindAssignment((AssignmentExpression)expression, contextSymbol,
                parent),

            // [..[In Categories]] -> 必须在DMS文件并且支持元数据字段的Event中
            SyntaxKinds.ObjectCollectionIteration => BindObjectIteration((ObjectCollectionIteration)expression),

            _ => AnalysisNodeFactory.EmptyExpression(parent)
        };
    }


    private void DeclareLocalVariable(AnalysisLocalVariable variable)
    {
        // mrs脚本中忽略containingModule
        LocalSymbol symbol = new(variable.Syntax);
        // 重复声明时，报错
        if (!DeclareLocalSymbol(symbol))
        {
            Raise(DiagnosticDescriptors.RepetitiveVariableDeclaration, variable.Syntax, variable.Syntax.Name);
        }

        variable.NameIdentifier.Bind(symbol);
        variable.Bind(symbol);
    }


    private void DeclareLocalFunction(FunctionDeclaration function)
    {
        FunctionSymbol functionSymbol = new(function);
        // Function
        if (function.HasReturn)
        {
            VariableDeclaration returnDecl =
                NodeFactory.CreateVariableDeclaration(function, function.NameIdentifier);
            returnDecl.UpdateFrom(function.NameIdentifier);
            LocalSymbol returnSymbol = new(returnDecl, null, functionSymbol);
            // 此时不会声明失败
            functionSymbol.DeclareLocalVariable(returnSymbol);
        }

        // Parameters
        function.Parameters.ForEach(p =>
        {
            ParameterSymbol pSymbol = new(p, functionSymbol);
            if (!functionSymbol.DeclareLocalVariable(pSymbol))
            {
                Raise(DiagnosticDescriptors.RepetitiveParameterSignature,
                    p.NameIdentifier, p.Name);
            }
        });

        if (function.InvalidContext)
        {
            Raise(DiagnosticDescriptors.CannotDeclareFunctionInContext, function.NameIdentifier);
        }
        else
        {
            if (!DeclareLocalSymbol(functionSymbol))
            {
                Raise(DiagnosticDescriptors.RepetitiveFunctionDecaration, function.NameIdentifier,
                    function.Name);
            }
        }

        _functionDeclareCache.Add(function.NameIdentifier, functionSymbol);
    }


    private AnalysisExpressionStatement BindExpressionStatement(ExpressionStatement statement,
        AnalysisNode? parent)
    {
        AnalysisExpression expression = BindExpression(statement.Expression, null, null);
        return AnalysisNodeFactory.ExpressionStatement(statement, expression, parent, WithSymbol);
    }


    private void UpdateBlock(AnalysisBlock target, Block source)
    {
        source.Statements.ForEach(s => target.AddChild(BindStatement(s, target)));
    }


    private void UpdateBlock(AnalysisBlock target, Block source, SyntaxKinds procedureKind)
    {
        _procedureStack.Push(procedureKind);
        UpdateBlock(target, source);
        _procedureStack.Pop();
    }


    private AnalysisBlock BindBlock(Block block, AnalysisNode? parent)
    {
        // 提前绑定行标签
        block.Labels.ForEach(DeclareLabel);
        AnalysisBlock stat = AnalysisNodeFactory.Block(block, parent, WithSymbol);
        UpdateBlock(stat, block);
        return stat;
    }


    private AnalysisBlock BindBlock(Block block, AnalysisNode? parent, SyntaxKinds procedureKind)
    {
        _procedureStack.Push(procedureKind);
        AnalysisBlock stat = BindBlock(block, parent);
        _procedureStack.Pop();
        return stat;
    }


    private AnalysisLocalConstant BindConstant(ConstantDeclaration declaration, AnalysisNode? parent)
    {
        AnalysisLocalConstant stat = AnalysisNodeFactory.LocalConstant(declaration, parent);
        // 声明符号
        LocalSymbol symbol = new(declaration);

        if (!DeclareLocalSymbol(symbol))
        {
            Raise(DiagnosticDescriptors.RepetitiveConstantDeclaration,
                declaration.NameIdentifier,
                declaration.Name);
        }

        stat.NameIdentifier.Bind(symbol);
        return stat;
    }


    private AnalysisDimStatement BindDim(DimStatement statement, AnalysisNode? parent)
    {
        AnalysisDimStatement stat = AnalysisNodeFactory.DimStatement(statement, parent, WithSymbol);

        // 创建单个变量声明
        statement.Declarations.ForEach(decl =>
        {
            AnalysisLocalVariable declaration = AnalysisNodeFactory.LocalVariable(decl, stat, WithSymbol);
            stat.AddChild(declaration);
            DeclareLocalVariable(declaration);
        });

        return stat;
    }


    private AnalysisIfStatement BindIf(IfStatement statement, AnalysisNode? parent)
    {
        // condition
        AnalysisExpression? condition = null;
        if (statement.ConditionExpression != null)
        {
            condition = BindExpression(statement.ConditionExpression, null, null);
        }

        // body
        AnalysisBlock body = BindBlock(statement.Body, null);
        // alternative
        AnalysisIfStatement? alternative = null;
        if (statement.ElseBranch != null)
        {
            alternative = BindIf(statement.ElseBranch, null);
        }

        return AnalysisNodeFactory.IfStatement(statement, condition, body, alternative, parent, WithSymbol);
    }


    private AnalysisRange BindRange(RangeExpression range, AnalysisNode? parent)
    {
        AnalysisExpression leftBound = BindExpression(range.LeftBoundary, WithSymbol, null);
        AnalysisExpression rightBound = BindExpression(range.RightBoundary, WithSymbol, null);
        // 检查左右区间是否能被转换成整数
        CheckTypeCompatible(leftBound, ValueTypeSymbol.Long);
        CheckTypeCompatible(rightBound, ValueTypeSymbol.Long);
        return AnalysisNodeFactory.Range(range, leftBound, rightBound, parent, WithSymbol);
    }
    

    private AnalysisForStatement BindFor(ForStatement statement, AnalysisNode? parent)
    {
        AnalysisIdentifier counter = BindIdentifier(statement.CounterIdentifier, null, null);
        AnalysisRange range = BindRange(statement.RangeExpression, null);

        // Step
        if (statement is { StepKeywordToken: not null, StepInteger.Value: 0 })
        {
            Raise(DiagnosticDescriptors.ForStepCannotBeZero, statement.StepInteger);
        }

        AnalysisBlock body = BindBlock(statement.Body, null, SyntaxKinds.ForKeywordToken);
        return AnalysisNodeFactory.ForStatement(statement, counter, range, body, parent, WithSymbol);
    }


    private AnalysisForEachStatement BindForEach(ForEachStatement statement, AnalysisNode? parent)
    {
        AnalysisIdentifier iterator = BindIdentifier(statement.ElementIdentifier, null, null);
        AnalysisExpression group = BindExpression(statement.GroupExpression, null, null);
        AnalysisBlock body = BindBlock(statement.Body, null, SyntaxKinds.ForKeywordToken);

        ITypeSymbol groupSymbol = group.GetTypeSymbol().GetFinalBindableBindingOrThis();
        if (!ValueTypeSymbol.IsAnyOrNull(groupSymbol) && !ValueTypeSymbol.IsCategorical(groupSymbol) && 
            !groupSymbol.IsUndefined && groupSymbol.LookupIndexer() == null)
        {
            Raise(DiagnosticDescriptors.TypeHasNoIndexer, statement.GroupExpression, groupSymbol.FullName);
        }

        return AnalysisNodeFactory.ForEachStatement(statement, iterator, group, body, parent, WithSymbol);
    }


    private AnalysisWhileStatement BindWhile(WhileStatement statement, AnalysisNode? parent)
    {
        AnalysisExpression condition = BindExpression(statement.ConditionExpression, null, null);
        AnalysisBlock block = BindBlock(statement.Body, null, SyntaxKinds.WhileKeywordToken);
        return AnalysisNodeFactory.WhileStatement(statement, condition, block, parent, WithSymbol);
    }


    private AnalysisDoStatement BindDo(DoStatement statement, AnalysisNode? parent)
    {
        AnalysisExpression condition = BindExpression(statement.ConditionExpression, null, null);
        AnalysisBlock body = BindBlock(statement.Body, null, SyntaxKinds.DoKeywordToken);
        return AnalysisNodeFactory.DoStatement(statement, condition, body, parent, WithSymbol);
    }


    private AnalysisSelectCaseClause BindSelectCaseClause(SelectCaseClause statement, AnalysisNode? parent)
    {
        List<AnalysisExpression> comparisons = statement.Conditions.Select(comparison =>
                BindExpression(comparison.Expression,
                    null,
                    null))
            .ToList();
        AnalysisBlock body = BindBlock(statement.Body, null);
        return AnalysisNodeFactory.SelectCaseClause(statement, comparisons, body, parent, WithSymbol);
    }


    private AnalysisSelectCaseStatement BindSelectCase(SelectStatement statement, AnalysisNode? parent)
    {
        AnalysisExpression expression = BindExpression(statement.Expression, null, null);
        AnalysisSelectCaseStatement stat =
            AnalysisNodeFactory.SelectCaseStatement(statement, expression, parent, WithSymbol);
        statement.ForEach(clause => stat.AddChild(BindSelectCaseClause(clause, stat)));
        return stat;
    }


    private AnalysisFunctionDeclaration BindFunction(FunctionDeclaration declaration)
    {
        Debug.Assert(!Identifier.IsDefaultOrEmpty(declaration.NameIdentifier));
        FunctionSymbol functionSymbol = _functionDeclareCache[declaration.NameIdentifier];
        AnalysisFunctionDeclaration func = AnalysisNodeFactory.FunctionDeclaration(declaration, functionSymbol, null);
        // Parameters
        func.GetChildren()
            .Where(node => node.BoundKind == AnalysisBoundKinds.Parameter)
            .ForEach(p => BindParameter((AnalysisParameter)p));
        // Body
        DomainSymbolTable? backupDomain = _currentDomain;
        _currentDomain = func.GetDomainSymbolTable();
        declaration.Body.Labels.ForEach(DeclareLabel);
        UpdateBlock(func.Body, declaration.Body, declaration.DeclareKeywordToken.Kind);
        _currentDomain = backupDomain;

        func.NameIdentifier.Bind(functionSymbol);

        return func;

        void BindParameter(AnalysisParameter parameter)
        {
            ITypeSymbol? symbol = functionSymbol.LookupNamedMember(parameter.Syntax.Name);

            if (symbol == null)
            {
                return;
            }

            parameter.NameIdentifier.Bind(symbol);
        }
    }


    private AnalysisWithStatement BindWith(WithStatement withStatement, AnalysisNode? parent)
    {
        AnalysisExpression expression = BindExpression(withStatement.Expression, null, null);
        // Body
        _withSymbolStack.Push(expression.GetTypeSymbol());
        AnalysisBlock body = BindBlock(withStatement.Body, null);
        _withSymbolStack.Pop();
        return AnalysisNodeFactory.WithStatement(withStatement, expression, body, parent, WithSymbol);
    }


    private void DeclareSectionLabel(SectionStatement section)
    {
        Debug.Assert(_treeSymbolTable != null);

        if (Identifier.IsDefaultOrEmpty((Identifier)section.NameIdentifier))
        {
            return;
        }

        LabelSymbol symbol = new(section);
        if (!_treeSymbolTable.DeclareSymbol(symbol))
        {
            Raise(DiagnosticDescriptors.DulplicateLineLabel, section.NameIdentifier, section.Name);
        }
    }


    private void DeclareLabel(LabelDeclaration label)
    {
        Debug.Assert(_treeSymbolTable != null);
        LabelSymbol symbol = new(label);

        if (_currentDomain != null)
        {
            if (_currentDomain.DeclareLabel(symbol))
            {
                return;
            }
        }
        else if (_withinDomain != null)
        {
            if (_withinDomain.DeclareLabel(symbol))
            {
                return;
            }
        }
        else if (_treeSymbolTable.DeclareLabel(symbol))
        {
            return;
        }
        
        Raise(DiagnosticDescriptors.DulplicateLineLabel, label.NameIdentifier, label.Name);
    }


    private AnalysisSection BindSection(SectionStatement section, AnalysisNode? parent)
    {
        AnalysisIdentifier name = AnalysisNodeFactory.Identifier((Identifier)section.NameIdentifier, null, WithSymbol);
        AnalysisSection node = AnalysisNodeFactory.Section(section, name, parent);
        // 查找标签
        LabelSymbol? label = _treeSymbolTable!.LookupLabel(section.Name);
        // 如果声明的行标签的声明节点不是参数section，不绑定
        if (label != null && label.Declaration == section)
        {
            name.Bind(label);
        }

        // 绑定语句块内容，Section语句块不带有自己的定义域
        UpdateBlock(node.Body, section.Body);

        return node;
    }


    private AnalysisLabel BindLabel(LabelDeclaration label, AnalysisNode? parent)
    {
        AnalysisLabel declaration = AnalysisNodeFactory.Label(label, parent);
        // 查找声明的符号
        LabelSymbol? symbol = _currentDomain?.LookupLabel(label.Name) ??
                              _withinDomain?.LookupLabel(label.Name) ??
                              _treeSymbolTable?.LookupLabel(label.Name);
        if (symbol != null)
        {
            declaration.NameIdentifier.Bind(symbol);
        }

        return declaration;
    }


    private AnalysisGotoStatement BindGoto(GotoStatement statement, AnalysisNode? parent)
    {
        AnalysisIdentifier? labelIdentifier = null;
        if (!Identifier.IsDefaultOrEmpty(statement.LabelIdentifier))
        {
            labelIdentifier = AnalysisNodeFactory.Identifier(statement.LabelIdentifier, null, WithSymbol);
            // Label:
            LabelSymbol? labelSymbol = null;
            // 在定义域中时，不查找语法树中的定义
            if (_currentDomain != null)
            {
                labelSymbol = _currentDomain.LookupLabel(statement.LabelIdentifier.Value);
            }
            else if (_withinDomain != null)
            {
                labelSymbol = _withinDomain.LookupLabel(statement.LabelIdentifier.Value);
            }
            else if (_treeSymbolTable != null)
            {
                labelSymbol = _treeSymbolTable.LookupLabel(statement.LabelIdentifier.Value);
            }

            if (labelSymbol == null)
            {
                Raise(DiagnosticDescriptors.UnknownLineLabel, statement.LabelIdentifier,
                    statement.LabelIdentifier.Value);
            }
            else
            {
                labelIdentifier.Bind(labelSymbol);
            }
        }

        return AnalysisNodeFactory.GotoStatement(statement, labelIdentifier, parent, WithSymbol);
    }


    private AnalysisExitStatement BindExit(ExitStatement statement, AnalysisNode? parent)
    {
        // 检查Exit后的过程是否存在
        if (statement.ProcedureKeywordToken != null &&
            !_procedureStack.Contains(statement.ProcedureKeywordToken.Kind))
        {
            Raise(DiagnosticDescriptors.UnknownProcedure, statement.ProcedureKeywordToken,
                SyntaxFacts.ConvertKeywordToString(statement.ProcedureKeywordToken.Kind,
                    KeywordContexts.Mrs));
        }

        return AnalysisNodeFactory.ExitStatement(statement, parent);
    }


    private AnalysisResumeStatement BindResume(ResumeStatement statement, AnalysisNode? parent)
    {
        if (!_procedureStack.Contains(SyntaxKinds.ForKeywordToken))
        {
            Raise(DiagnosticDescriptors.ResumeOnlyCanBeUsedInForLoop, statement);
        }

        return AnalysisNodeFactory.ResumeStatement(statement, parent);
    }


    private AnalysisOnErrorStatement BindOnError(OnErrorStatement statement, AnalysisNode? parent)
    {
        AnalysisOnErrorStatement node = AnalysisNodeFactory.OnErrorStatement(statement, parent);
        // Goto .
        if (statement.JumpStatement != null)
        {
            node.AddChild(BindGoto(statement.JumpStatement, node));
        }
        // Resume
        else if (statement.ResumeStatement != null)
        {
            node.AddChild(BindResume(statement.ResumeStatement, node));
        }

        return node;
    }


    private AnalysisTreeInclude BindTreeInclude(SyntaxTreeIncludeNode include, AnalysisNode? parent)
    {
        AnalysisTreeInclude node = AnalysisNodeFactory.TreeInclude(include, parent, WithSymbol);

        SyntaxTree? tree = include.GetSyntaxTree();
        if (tree == null)
        {
            return node;
        }

        AnalysisTree boundTree = Bind(tree);
        node.UpdateAnalysisTree(boundTree);

        return node;
    }


    private AnalysisStatement BindStatement(Statement statement, AnalysisNode? parent)
    {
        return statement.Kind switch
        {
            SyntaxKinds.Block => BindBlock((Block)statement, parent),
            SyntaxKinds.ExpressionStatement => BindExpressionStatement((ExpressionStatement)statement, parent),
            SyntaxKinds.DimStatement => BindDim((DimStatement)statement, parent),
            SyntaxKinds.IfStatement => BindIf((IfStatement)statement, parent),
            SyntaxKinds.ForStatement => BindFor((ForStatement)statement, parent),
            SyntaxKinds.ForEachStatement => BindForEach((ForEachStatement)statement, parent),
            SyntaxKinds.WhileStatement => BindWhile((WhileStatement)statement, parent),
            SyntaxKinds.DoStatement => BindDo((DoStatement)statement, parent),
            SyntaxKinds.SelectStatement => BindSelectCase((SelectStatement)statement, parent),
            SyntaxKinds.WithStatement => BindWith((WithStatement)statement, parent),
            SyntaxKinds.ConstantDeclaration => BindConstant((ConstantDeclaration)statement, parent),
            SyntaxKinds.FunctionDeclaration => BindFunction((FunctionDeclaration)statement),
            SyntaxKinds.GotoStatement => BindGoto((GotoStatement)statement, parent),
            SyntaxKinds.ExitStatement => BindExit((ExitStatement)statement, parent),
            SyntaxKinds.ResumeStatement => BindResume((ResumeStatement)statement, parent),
            SyntaxKinds.SectionStatement => BindSection((SectionStatement)statement, parent),
            SyntaxKinds.OnErrorStatement => BindOnError((OnErrorStatement)statement, parent),
            SyntaxKinds.Label => BindLabel((LabelDeclaration)statement, parent),
            SyntaxKinds.SyntaxTreeInclude => BindTreeInclude((SyntaxTreeIncludeNode)statement, parent),
            _ => AnalysisEmptyStatement.Default
        };
    }
}